package com.qingcheng.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.qingcheng.dao.BrandMapper;
import com.qingcheng.dao.CategoryMapper;
import com.qingcheng.dao.SpecMapper;
import com.qingcheng.enums.CacheKey;
import com.qingcheng.pojo.goods.Category;
import com.qingcheng.pojo.goods.Sku;
import com.qingcheng.service.goods.SkuSearchService;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @ProjectName: qingcheng_parent
 * @ClassName: SkuSearchServiceImpl
 * @Time: 2019/7/10
 * @Author: zhou24
 * @Description:
 * @Experience:
 */
@Service
public class SkuSearchServiceImpl implements SkuSearchService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private BrandMapper brandMapper;

    @Autowired
    private SpecMapper specMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public Map search(Map<String, String> searchMap) {

        //1、封装查询请求
        SearchRequest searchRequest = new SearchRequest("sku");
        searchRequest.types("doc");//设置查询的类型

        //查询源构建器
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //布尔查询构建器
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        //1.1关键字搜索
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", searchMap.get("keywords"));
        boolQueryBuilder.must(matchQueryBuilder);

        //1.2商品分类过滤
        if (searchMap.get("category") != null) {
            TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("categoryName.keyword", searchMap.get("category"));
            boolQueryBuilder.filter(termQueryBuilder);
        }

        //1.3品牌过滤
        if (searchMap.get("brand") != null) {
            TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("brandName.keyword", searchMap.get("brand"));
            boolQueryBuilder.filter(termQueryBuilder);
        }

        //1.4规格过滤 for.if
        for (String key : searchMap.keySet()) {
            if (key.startsWith("spec.")) {
                TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(key + ".keyword", searchMap.get(key));
                boolQueryBuilder.filter(termQueryBuilder);
            }
        }

        //1.5价格过滤 if
        if (searchMap.get("price") != null) {
            String[] prices = searchMap.get("price").split("-");
            if (!prices[0].equals("0")) {
                RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price").gte(prices[0] + "00");
                boolQueryBuilder.filter(rangeQueryBuilder);
            }
            if (!prices[1].equals("*")) {
                RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price").lte(prices[1] + "00");
                boolQueryBuilder.filter(rangeQueryBuilder);
            }
        }

        //分装查询条件
        searchSourceBuilder.query(boolQueryBuilder);

        //分页
        Integer pageNo = Integer.parseInt(searchMap.get("pageNo"));
        Integer pageSize = 30;
        //起始记录下标
        int fromIndex = (pageNo - 1) * pageSize;
        searchSourceBuilder.from(fromIndex);
        searchSourceBuilder.size(pageSize);

        //聚合查询（商品分类）
        //1.2聚合查询（商品分类）
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("sku_category").field("categoryName.keyword");
        //categoryName==》categoryName.keyword
        searchSourceBuilder.aggregation(termsAggregationBuilder);

        //排序
        if (!"".equals(searchMap.get("sort"))) {
            searchSourceBuilder.sort(searchMap.get("sort"), SortOrder.valueOf(searchMap.get("sortOrder")));
        }

        //高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("name").preTags("<font style='color:red'>").postTags("</font>");
        searchSourceBuilder.highlighter(highlightBuilder);

        searchRequest.source(searchSourceBuilder);

        //2、分装查询结果
        Map resultMap = new HashMap();
        try {
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            SearchHits searchHits = searchResponse.getHits();
            SearchHit[] hits = searchHits.getHits();

            //2.1、商品列表
            List<Map<String, Object>> resultList = new ArrayList<>();
            for (SearchHit hit : hits) {
                Map<String, Object> skuMap = hit.getSourceAsMap();

                //高亮处理
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                HighlightField name = highlightFields.get("name");
                Text[] fragments = name.fragments();
                skuMap.put("name", fragments[0].toString());

                resultList.add(skuMap);
            }
            resultMap.put("rows", resultList);

            //2.2商品分类列表
            Aggregations aggregations = searchResponse.getAggregations();
            Map<String, Aggregation> aggregationMap = aggregations.getAsMap();
            Terms terms = (Terms) aggregationMap.get("sku_category");
            List<? extends Terms.Bucket> buckets = terms.getBuckets();
            ArrayList<Object> categoryList = new ArrayList<>();
            for (Terms.Bucket bucket : buckets) {
                categoryList.add(bucket.getKeyAsString());
            }
            resultMap.put("categoryList", categoryList);

            //默认的categoryName设定
            String categoryName = "";
            if (searchMap.get("category") == null) {
                if (categoryList.size() > 0) {
                    categoryName = (String) categoryList.get(0);
                    System.out.println("商品分类1" + categoryName);
                }
            } else {
                categoryName = searchMap.get("category");
                System.out.println("商品分类2" + categoryName);
            }

            System.out.println("品牌");
            //2.3品牌列表
            List<Map> brandList = brandMapper.findListByCategoryName(categoryName);
            ;

//            if (!redisTemplate.hasKey(categoryName)) {
//                saveBrandListByCategory();
//            }
//            brandList = (List<Map>) redisTemplate.boundValueOps(categoryName).get();

            brandList = brandMapper.findListByCategoryName(categoryName);

            resultMap.put("brandList", brandList);

            //2.4规格列表
            List<Map> specList = specMapper.findListByCategoryName(categoryName);

//            if (!redisTemplate.hasKey("spec." + categoryName)) {
//                saveSpecListByCategory();
//            }
//            specList = (List<Map>) redisTemplate.boundValueOps("spec." + categoryName).get();

            specList = specMapper.findListByCategoryName(categoryName);

            for (Map spec : specList) {
                //规格选项列表
                String[] options = ((String) spec.get("options")).split(",");
                spec.put("options", options);
            }
            resultMap.put("specList", specList);
            //2.5url处理

            //2.6页码
            long totalCount = searchHits.getTotalHits();
            long pageCount = (totalCount % pageSize == 0) ? totalCount / pageSize : (totalCount / pageSize + 1);
            resultMap.put("totalPages", pageCount);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return resultMap;
    }

    @Autowired
    private CategoryMapper categoryMapper;

    public void saveBrandListByCategory() {
        System.out.println("saveBrandList");
        List<Category> categories = categoryMapper.selectAll();
        for (Category category : categories) {
            List<Map> categoryBrand = brandMapper.findListByCategoryName(category.getName());
            redisTemplate.boundValueOps(category.getName()).set(categoryBrand);
            redisTemplate.boundValueOps(category.getName()).expire( (int) (1 + Math.random() * 100),TimeUnit.MINUTES);
        }
        System.out.println("saveBrandListByCategory");
    }

    public void saveSpecListByCategory() {
        System.out.println("saveSpecList");
        List<Category> categories = categoryMapper.selectAll();
        for (Category category : categories) {
            List<Map> specList = specMapper.findListByCategoryName(category.getName());
            redisTemplate.boundValueOps("spec." + category.getName()).set(specList);
            redisTemplate.expire("spec." + category.getName(), (int) (1 + Math.random() * 100), TimeUnit.MINUTES);
        }
        System.out.println("saveSpecListByCategory");
    }

}
